#include "Date.h"
int Date::n = 0;
// 构造函数
Date::Date(int year, int month, int day)
{
    if (year >= 0 && (month >= 1 && month <= 12) && (day >= 1 && day <= GetMonthDay(year, month)))
    {
        this->_year = year;
        this->_month = month;
        this->_day = day;
    }
    else
    {
        // 非法输入
        cerr << "Error: 非法输入，日期不符合规范" << endl;
    }
}
/*
// 用初始化列表构造函数
Date::Date(int year, int month, int day):_year(year),_month(month),_day(day)
{
    if (year >= 0 && (month >= 1 && month <= 12) && (day >= 1 && day <= GetMonthDay(year, month)))
    {
        return;
    }
    else
    {
        // 非法输入
        _year = 0;
        _month = 1;
        _day = 1;
        cerr << "Error: 非法输入，日期不符合规范" << endl;
    }
}
*/

// 拷贝构造——Date d2(d1)
// 一定要加引用，否则会造成递归拷贝
Date::Date(const Date &d)
{
    this->_year = d._year;
    this->_month = d._month;
    this->_day = d._day;
}
// 赋值拷贝
Date &Date::operator=(const Date &d)
{
    // 要是自己给自己赋值就没必要执行了
    if (this != &d)
    {
        this->_year = d._year;
        this->_month = d._month;
        this->_day = d._day;
    }
    // i=j=k,为了可以连续赋值拷贝
    return *this;
}
// 运算符重载——实现日期的比较
bool Date::operator==(const Date &d) const
{ // d1 == d2或者 d1.operatoe(&d1,d2)
    return this->_year == d._year &&
           this->_month == d._month &&
           this->_day == d._day;
}
bool Date::operator>(const Date &d) const
{ // d1 > d2
    if (this->_year > d._year)
        return true;
    else if (this->_year == d._year && this->_month > d._month)
        return true;
    else if (this->_year == d._year && this->_month == d._month && this->_day > d._day)
        return true;
    else
        return false;
}
bool Date::operator>=(const Date &d) const
{ // d1 >= d2
    // 可以复用上面的代码实现
    return *this > d || *this == d;
}
bool Date::operator<(const Date &d) const
{ // d1 < d2
    return !(*this >= d);
}
bool Date::operator<=(const Date &d) const
{ // d1 <= d2
    return !(*this > d);
}
bool Date::operator!=(const Date &d) const
{ // d1 != d2
    return !(*this == d);
}
// 运算符重载——实现日期的加减 // d1 + 10
Date Date::operator+(int day) const
{
    // 拷贝构造
    Date d1(*this);
    d1 += day;
    /*
    d1._day += day;
    while (d1._day > GetMonthDay(d1._year, d1._month))
    {
        // 进入循环，说明现在日期还不合法
        d1._day -= GetMonthDay(d1._year, d1._month);
        d1._month++;
        // 年份进位
        if (d1._month == 13)
        {
            d1._year++;
            d1._month = 1;
        }
    }
    */
    return d1;
}
Date &Date::operator+=(int day)
{ // d1 += 10
    if (this->_day < 0)
    { // d1 += (-10)
        // 如果加上的是负数
        return *this -= (-day);
    }
    this->_day += day;
    while (this->_day > GetMonthDay(this->_year, this->_month))
    {
        // 进入循环，说明现在日期还不合法
        this->_day -= GetMonthDay(this->_year, this->_month);
        this->_month++;
        // 年份进位
        if (this->_month == 13)
        {
            this->_year++;
            this->_month = 1;
        }
    }
    // 如果+=复用+，那每一次相加就是一次对象的创建
    // 也是一次次构造函数和析构函数的调用
    //*this = *this + day;
    return *this;
}
Date Date::operator-(int day) const // d1 - 10
{
    // 拷贝构造
    Date d1(*this);
    d1 -= day;
    /*
    d1._day -= day;
    if (d1._day > 0)
        return d1;

    while (d1._day < 0)
    { //_day不合法要继续处理
        d1._month--;
        if (d1._month == 0)
        {
            d1._year--;
            d1._month = 12;
        }
        d1._day += GetMonthDay(d1._year, d1._month);
    }
    */
    return d1;
}
Date &Date::operator-=(int day)
{ // d1 -= 10
    if (day < 0)
    { // d1 -= (-10)
        // 如果减去的是负数呢？
        return *this += (-day);
    }
    this->_day -= day;
    if (this->_day > 0)
        return *this;

    while (this->_day < 0) //_day不合法要继续处理
    {
        this->_month--;
        if (this->_month == 0)
        {
            this->_year--;
            this->_month = 12;
        }
        this->_day += GetMonthDay(this->_year, this->_month);
    }
    //*this = (*this - day);
    return *this;
}
//++d1 前置加加
Date &Date::operator++()
{
    *this += 1;
    if (this->_day > GetMonthDay(this->_year, this->_month))
    {
        this->_day = 1;
        this->_month++;
    }
    if (this->_month > 12)
    {
        this->_year++;
        this->_month = 1;
    }
    return *this; // 返回加之后的值
}
// d1++ 后置加加，为了函数重载参数加个int
Date Date::operator++(int)
{
    Date tmp(*this);
    ++*this;
    return tmp; // 返回加之前的值
}
//--d1
Date &Date::operator--()
{
    *this -= 1;
    if (this->_day == 0)
    {
        this->_month--;
        if (this->_month == 0)
        {
            this->_year--;
            this->_month = 12;
        }
        this->_day = GetMonthDay(this->_year, this->_month);
    }
    return *this;
}
// d1--
Date Date::operator--(int)
{
    Date tmp(*this);
    --*this;
    return tmp;
}

// 运算符重载——日期-日期，可以转化为：
// 小的日期一直累加到大的天数，就是两个日期相差多少天
int Date::operator-(const Date &d) const
{
    int flag = 1;
    Date max = *this;
    Date min = d;
    // 确定两个日期谁大谁小
    if (*this < d)
    {
        max = d;
        min = *this;
        flag = -1;
    }

    int n = 0;
    while (min != max)
    {
        ++min;
        ++n;
    }

    return n * flag;
}
// 取地址重载——很少写
Date *Date::operator&()
{
    return this;
}
// const Date d1; &d1,const不能调用非const
const Date *Date::operator&() const
{
    return this;
}

// 析构函数
Date::~Date()
{
    cout << ++Date::n << "->" << "~Date" << endl;
}

void Date::Print() const
{ // void Print(Date* this)——d1.Print(&d1)
    cout << _year << "年" << _month << "月" << _day << "日" << endl;
}

// 计算当年月份的天数
int Date::GetMonthDay(const int& year, const int& month)
{
    // 十二个月每月的日期（不是闰年）
    static int daysInmonth[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (LeapYear(year) && month == 2)
        return 29;

    return daysInmonth[month];
}
// 判断当前年份是不是闰年
bool Date::LeapYear(const int& year)
{
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
/*
//d1.operator<<(cout)/d1 << cout;不用友元就要这样才能调用。
void Date::operator<<(ostream& out){
    out << _year << "年" << _month << "月" << _day << "日" << endl;
}
*/

ostream& operator<<(ostream& out,const Date& d){
    out << d._year << "年"  <<d. _month << "月" << d._day << "日" << endl;
    return out;
}
istream& operator>>(istream& in, Date& d){
    in >> d._year >> d. _month >> d._day;
    return in;
}